package org.jaaksi.customviewdemo.chart

import android.content.res.Resources
import android.graphics.Path

private const val defaultSmoothFactor = 0.20f

val screenWidth = Resources.getSystem().displayMetrics.widthPixels

val screenHeight = Resources.getSystem().displayMetrics.heightPixels

fun List<DataPoint>.toSmoothLinePath3(path: Path, smoothFactor: Float = defaultSmoothFactor) {
    // 找到所有value为0的下标，分段
    path.reset()
    path.moveTo(this.first().screenPositionX, this.first().screenPositionY)
    var curr = 0
    var startExtraPoint: DataPoint?
    var endExtraPoint: DataPoint?
    this.forEachIndexed { index, dataPoint ->
        startExtraPoint = null
        endExtraPoint = null
        if (dataPoint.value == 0f) {
            if (this[index + 1].value > 30f) {
                if (this[index - 1].value > 0f) {
                    endExtraPoint = this[index + 1]
                }
                if (curr != 0 && this[curr + 1].value < 0f) {// this[curr+1].value<0f
                    startExtraPoint = this[curr - 1]
                }

            }
            this.subList(curr, index + 1)
                .toSmoothLinePath(path, false, smoothFactor, startExtraPoint, endExtraPoint)

            curr = index
        }
    }
    startExtraPoint = null
    if (this[curr + 1].value < 0f) {
        startExtraPoint = this[curr - 1]
    }

    this.subList(curr, this.lastIndex + 1)
        .toSmoothLinePath(path, false, smoothFactor, startExtraPoint)

}

fun List<DataPoint>.toSmoothLinePath(
    path: Path,
    resetPath: Boolean = true,
    smoothFactor: Float = defaultSmoothFactor,
    startExtraPoint: DataPoint? = null,
    endExtraPoint: DataPoint? = null,
) {
    var thisPointX: Float
    var thisPointY: Float
    var nextPointX: Float
    var nextPointY: Float
    var startDiffX: Float
    var startDiffY: Float
    var endDiffX: Float
    var endDiffY: Float
    var firstControlX: Float
    var firstControlY: Float
    var secondControlX: Float
    var secondControlY: Float
    if (resetPath) {
        path.reset()
        path.moveTo(this.first().screenPositionX, this.first().screenPositionY)
    }

    for (i in 0 until this.size - 1) {

        thisPointX = this[i].screenPositionX
        thisPointY = this[i].screenPositionY

        nextPointX = this[i + 1].screenPositionX
        nextPointY = this[i + 1].screenPositionY
        if (startExtraPoint != null && i == 0) { // 第一个元素
            println(">> ext this[i + 1].value = ${this[i + 1].value}")
            startDiffX = nextPointX - startExtraPoint.screenPositionX
            startDiffY = nextPointY - startExtraPoint.screenPositionY
        } else {
            startDiffX = nextPointX - this[safeIndex(this.size, i - 1)].screenPositionX
            startDiffY = nextPointY - this[safeIndex(this.size, i - 1)].screenPositionY
        }

        if (endExtraPoint != null && i == this.size - 2) { // 最后一个元素
            endDiffX = endExtraPoint.screenPositionX - thisPointX
            endDiffY = endExtraPoint.screenPositionY - thisPointY
        } else {
            endDiffX = this[safeIndex(this.size, i + 2)].screenPositionX - thisPointX
            endDiffY = this[safeIndex(this.size, i + 2)].screenPositionY - thisPointY
        }



        firstControlX = thisPointX + smoothFactor * startDiffX
        firstControlY = thisPointY + smoothFactor * startDiffY

        secondControlX = nextPointX - smoothFactor * endDiffX
        secondControlY = nextPointY - smoothFactor * endDiffY

        path.cubicTo(
            firstControlX,
            firstControlY,
            secondControlX,
            secondControlY,
            nextPointX,
            nextPointY
        )
    }
}

fun List<DataPoint>.toSmoothLinePath(smoothFactor: Float = defaultSmoothFactor): Path {
    var thisPointX: Float
    var thisPointY: Float
    var nextPointX: Float
    var nextPointY: Float
    var startDiffX: Float
    var startDiffY: Float
    var endDiffX: Float
    var endDiffY: Float
    var firstControlX: Float
    var firstControlY: Float
    var secondControlX: Float
    var secondControlY: Float

    val res = Path()
    res.moveTo(this.first().screenPositionX, this.first().screenPositionY)

    for (i in 0 until this.size - 1) {

        thisPointX = this[i].screenPositionX
        thisPointY = this[i].screenPositionY

        nextPointX = this[i + 1].screenPositionX
        nextPointY = this[i + 1].screenPositionY

        startDiffX = nextPointX - this[safeIndex(this.size, i - 1)].screenPositionX
        startDiffY = nextPointY - this[safeIndex(this.size, i - 1)].screenPositionY

        endDiffX = this[safeIndex(this.size, i + 2)].screenPositionX - thisPointX
        endDiffY = this[safeIndex(this.size, i + 2)].screenPositionY - thisPointY

        firstControlX = thisPointX + smoothFactor * startDiffX
        firstControlY = thisPointY + smoothFactor * startDiffY

        secondControlX = nextPointX - smoothFactor * endDiffX
        secondControlY = nextPointY - smoothFactor * endDiffY

        res.cubicTo(
            firstControlX,
            firstControlY,
            secondControlX,
            secondControlY,
            nextPointX,
            nextPointY
        )
    }

    return res
}

private fun safeIndex(setSize: Int, i: Int): Int {
    return when {
        i > setSize - 1 -> setSize - 1
        i < 0 -> 0
        else -> i
    }
}